<template>
  <div>
    <canvas></canvas>
  </div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue'
import * as earcut from 'earcut'
import {
  Engine,
  Scene,
  ArcRotateCamera,
  Vector3,
  MeshBuilder,
  HemisphericLight,
  Color3,
  StandardMaterial,
  DynamicTexture,
  Texture,
  Vector4,
  Animation
} from '@babylonjs/core'

onMounted(() => {
  window.earcut = earcut
  const canvas = document.querySelector('canvas')! as HTMLCanvasElement
  // 创建引擎
  const engine = new Engine(canvas, true)
  // 创建场景
  const scene = new Scene(engine)
  // 创建相机
  const Camera = new ArcRotateCamera('camera', 0, 0, 10, Vector3.Zero(), scene)
  // 运用相机和画布关联起来
  Camera.attachControl(canvas, true)
  // 添加灯光到场景中(环境灯)
  const light = new HemisphericLight('light', new Vector3(1, 1, 1), scene)
  // 创建小车
  //base
  // 两个点（x,z平面才有）
  const faceUV = []
  faceUV[0] = new Vector4(0, 0.5, 0.38, 1)
  faceUV[1] = new Vector4(0, 0, 1, 0.5)
  const carMat = new StandardMaterial('carMat', scene)
  carMat.diffuseTexture = new Texture('https://assets.babylonjs.com/environments/car.png')
  const outline = [new Vector3(-0.3, 0, -0.1), new Vector3(0.2, 0, -0.1)]

  //curved front
  // 圆弧
  for (let i = 0; i < 20; i++) {
    outline.push(
      new Vector3(0.2 * Math.cos((i * Math.PI) / 40), 0, 0.2 * Math.sin((i * Math.PI) / 40) - 0.1)
    )
  }

  //top
  outline.push(new Vector3(0, 0, 0.1))
  outline.push(new Vector3(-0.3, 0, 0.1))
  // y没有值，depth就拉升了0.2
  const car = MeshBuilder.ExtrudePolygon('car', { shape: outline, depth: 0.2, faceUV: faceUV })
  car.material = carMat
  // 轮子
  const focuUv = []
  // 车轮的上面和下面
  focuUv[0] = focuUv[2] = new Vector4(0, 0, 1, 1)
  // 车轮的侧面
  focuUv[1] = new Vector4(0, 0.5, 0, 0.5)
  const wheelMat = new StandardMaterial('whellMat', scene)
  wheelMat.diffuseTexture = new Texture('https://assets.babylonjs.com/environments/wheel.png')
  const wheelRB = MeshBuilder.CreateCylinder('wheelRB', {
    diameter: 0.125,
    height: 0.05,
    faceUV: focuUv
  })
  wheelRB.material = wheelMat

  wheelRB.parent = car
  wheelRB.position.z = -0.1
  wheelRB.position.x = -0.2
  wheelRB.position.y = 0.035

  const wheelRF = wheelRB.clone('wheelRF')
  wheelRF.position.x = 0.1

  const wheelLB = wheelRB.clone('wheelLB')
  wheelLB.position.y = -0.2 - 0.035

  const wheelLF = wheelRF.clone('wheelLF')
  wheelLF.position.y = -0.2 - 0.035
  // 创建车轮的材质
  car.rotation.x = -Math.PI / 2
  showAxis(3, scene)
  // 添加轮子动画
  const animWheel = new Animation(
    'wheelAnimation',
    'rotation.y',
    30,
    Animation.ANIMATIONTYPE_FLOAT,
    Animation.ANIMATIONLOOPMODE_CYCLE
  )
  // 定义关键帧
  const wheelKeys = []
  wheelKeys.push({
    frame: 0,
    value: 0
  })
  wheelKeys.push({
    frame: 30,
    value: Math.PI / 2
  })
  // 把关键帧加到动画
  animWheel.setKeys(wheelKeys)
  wheelRB.animations.push(animWheel)
  // 场景更新动画(是谁做动画，第几帧开始，第几帧结束，是否循环播放)
  scene.beginAnimation(wheelRB, 0, 30, true)

  engine.runRenderLoop(() => {
    scene.render()
  })
  window.addEventListener('resize', function () {
    engine.resize()
  })
})
const showAxis = (size: number, scene: Scene) => {
  const makeTextPlane = (text: string, color: any, size: number) => {
    const dynamicTexture = new DynamicTexture('DynamicTexture', 50, scene, true)
    dynamicTexture.hasAlpha = true
    dynamicTexture.drawText(text, 5, 40, 'bold 36px Arial', color, 'transparent', true)

    const planeMat = new StandardMaterial('TextPlaneMaterial', scene)
    planeMat.backFaceCulling = false
    planeMat.specularColor = new Color3(0, 0, 0)
    planeMat.diffuseTexture = dynamicTexture
    const plane = MeshBuilder.CreatePlane('TextPlane', { size })
    plane.material = planeMat
    return plane
  }

  const axisX = MeshBuilder.CreateLines('axisX', {
    points: [
      Vector3.Zero(),
      new Vector3(size, 0, 0),
      new Vector3(size * 0.95, 0.05 * size, 0),
      new Vector3(size, 0, 0),
      new Vector3(size * 0.95, -0.05 * size, 0)
    ]
  })
  axisX.color = new Color3(1, 0, 0)
  const xChar = makeTextPlane('X', 'red', size / 10)
  xChar.position = new Vector3(0.9 * size, -0.05 * size, 0)

  const axisY = MeshBuilder.CreateLines('axisY', {
    points: [
      Vector3.Zero(),
      new Vector3(0, size, 0),
      new Vector3(-0.05 * size, size * 0.95, 0),
      new Vector3(0, size, 0),
      new Vector3(0.05 * size, size * 0.95, 0)
    ]
  })
  axisY.color = new Color3(0, 1, 0)
  const yChar = makeTextPlane('Y', 'green', size / 10)
  yChar.position = new Vector3(0, 0.9 * size, -0.05 * size)

  const axisZ = MeshBuilder.CreateLines('axisZ', {
    points: [
      Vector3.Zero(),
      new Vector3(0, 0, size),
      new Vector3(0, -0.05 * size, size * 0.95),
      new Vector3(0, 0, size),
      new Vector3(0, 0.05 * size, size * 0.95)
    ]
  })
  axisZ.color = new Color3(0, 0, 1)
  const zChar = makeTextPlane('Z', 'blue', size / 10)
  zChar.position = new Vector3(0, 0.05 * size, 0.9 * size)
}
</script>

<style></style>
